package br.com.foxinline.servico;

import br.com.foxinline.modelo.Grupo;
import br.com.foxinline.modelo.Usuario;
import br.com.foxinline.utilitario.Msg;
import java.beans.Transient;
import java.security.Principal;
import java.util.List;
import javax.ejb.Stateless;
import javax.faces.context.FacesContext;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;

/**
 *
 * @author ely
 */
@Stateless
//@DeclareRoles(GrupoUtilitario.ADMINISTRADOR)
public class UsuarioServico extends ServicoGenerico<Usuario> {

    private Long quantidadeRegistrosResults;

    public UsuarioServico() {
        super(Usuario.class);
    }

    @Override
//    @RolesAllowed(GrupoUtilitario.ADMINISTRADOR)
    public void deletar(Usuario entity) {
        super.deletar(entity);
    }

    public void saveUser(String confirm, Usuario user) {
        try {
            if (checkUserName(user)) {
                if (compareToPassword(confirm, user)) {
                    user.setSenha(Usuario.encryptPassword(user.getSenha()));

                    salvar(user);
                } else {
                    Msg.messagemError("Senhas não conferem");
                }
            } else {
                Msg.messagemError("O campo nome é obrigatório");
            }
        } catch (Exception erro) {
        }
    }

    public void updateUser(String confirm, String passwordOld, String passwordNew, Usuario user) {
        try {
            if (checkUserPassword(passwordOld, user)) {
                if (compareToPassword(confirm, passwordNew)) {
                    user.setSenha(Usuario.encryptPassword(passwordNew));
                    atualizar(user);
                } else {
                    Msg.messagemError("Senhas não conferem");
                }
            } else {
                Msg.messagemError("Senha antiga não confere");
            }
        } catch (Exception erro) {
        }

    }

    public void updateAcess(Usuario user) {
        try {
            atualizar(user);
            Msg.messagemInfo("Nível de Acesso Atualizado com Sucesso");
        } catch (Exception erro) {
        }
    }

    /**
     * Compara senha do usuário
     *
     * @param comparasenha
     * @param usuario
     * @return
     */
    public boolean compareToPassword(String confirm, Usuario user) {
        return user.getSenha().equals(confirm);
    }

    public boolean compareToPassword(String confirm, String passwordNew) {
        return passwordNew.equals(confirm);

    }

    /**
     * verifica se o campo name está vazio
     *
     * @param verificacampo
     * @return
     */
    public boolean checkUserName(Usuario user) {
        return !user.getNome().equals("");
    }

    /**
     * Compara senha Cripitografada (Senha antiga)
     *
     * @param compara senha
     * @param cripitografia
     * @return
     */
    public boolean checkUserPassword(String senha, Usuario user) {
        String s = Usuario.encryptPassword(senha);
        return s.equals(user.getSenha());
    }

    public Usuario existLogin(String doc) {
        Usuario usuario;
        String sql = "Select u from Usuario u "
                + "where lower(u.login) like lower(:doc)";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("doc", doc);
        try {
            usuario = (Usuario) query.getResultList().get(0);

        } catch (NoResultException nr) {
            return null;
        } catch (NonUniqueResultException nre) {
            return null;
        } catch (Exception e) {
            return null;
        }

        return usuario;
    }

    public Usuario verifySystemUserForLogin(String nome) {
        if (nome == null) {
            return null;
        }
        Usuario usr;
        try {
            final String sql = "select u from Usuario u where "
                    + "u.login like :nome";
            Query query = getEntityManager().createQuery(sql);
            query.setParameter("nome", nome);
            usr = (Usuario) query.getSingleResult();

        } catch (Exception e) {
            System.err.println("Nenhum usuário encontrado");
            return null;
        }
        return usr;
    }

    public Usuario getCurrentUser() {
        final Principal userPrincipal = FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
        if (userPrincipal != null) {
            return verifySystemUserForLogin(userPrincipal.getName());
        }

        return null;
    }

    public String getNomeUsuario(String usuario) {
        String sql = "SELECT u.nome FROM Usuario u ";
        sql += " where ";

        if ((usuario != null) && !usuario.equals("")) {
            sql += " lower(u.login) like lower(:login) ";
        }
//        sql += " and u.ativo = TRUE";

        Query query = getEntityManager().createQuery(sql);

        if ((usuario != null) && !usuario.equals("")) {
            query.setParameter("login", usuario);
        }
        return (String) query.getSingleResult();
    }

    public boolean isAdmin() {

        Usuario usuario = getCurrentUser();

        return isAdminAuxiliar(usuario);
    }

    private boolean isAdminAuxiliar(Usuario usuario) {
        for (Grupo grupo : usuario.getGrupos()) {
            if (grupo.getNome().toLowerCase().contains("administrador")) {
                return true;
            }
        }
        return false;
    }

    /**
     * Pesquisar Usuário
     *
     * @param pesquisarUsuario
     * @return
     */
    @Override
    public List<Usuario> pesquisar(Usuario entidade, int first, int pageSize) {

        String select = "select u ";
        String orderBy = "order by u.id asc";

        String sql = "from " + Usuario.class.getSimpleName() + " u WHERE ";

        if (entidade.getNome() != null && !entidade.getNome().isEmpty()) {
            sql += "lower(u.nome) like lower(:nome) AND ";
        }

        sql += "1=1";

        Query query = getEntityManager().createQuery(select.concat(sql).concat(orderBy));

        setQuantidadeRegistros(sql, query, entidade);

        setParameters(entidade, query);

        query.setFirstResult(first).setMaxResults(pageSize);

        return query.getResultList();
    }

    @Transient
    private void setParameters(Usuario entidade, Query query) {
        if (entidade.getNome() != null && !entidade.getNome().isEmpty()) {
            query.setParameter("nome", "%" + entidade.getNome() + "%");
        }
    }

    private void setQuantidadeRegistros(String sql, Query query, Usuario entidade) {

        String select = "SELECT count(u) ";

        query = getEntityManager().createQuery(select + sql);

        setParameters(entidade, query);

        quantidadeRegistrosResults = (Long) query.getSingleResult();
    }

    @Override
    public Long quantidadeRegistros() {
        return quantidadeRegistrosResults;
    }
}
